﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Zeta;
using Zeta.Common.Helpers;
using Zeta.Internals.Actors;
using Zeta.TreeSharp;
using Action = Zeta.TreeSharp.Action;
using Zeta.Common;

using IncubusCC.Settings;

namespace IncubusCC.Helpers
{
    public static class Common
    {
        public static Composite CreateWaitWhileStunned()
        {
            return
                new Decorator(ret =>
                    ZetaDia.Me.IsFeared ||
                    ZetaDia.Me.IsStunned ||
                    ZetaDia.Me.IsFrozen ||
                    ZetaDia.Me.IsBlind,
                    new Action(ret => RunStatus.Success)
                );
        }

        /// <summary>
        /// Creates  a behavior that makes sure the bot doesn't perform any actions in combat if the player is incapacitated
        /// </summary>
        /// <returns></returns>
        /// <remarks>Created 2012-07-11</remarks>
        public static Composite CreateWaitWhileIncapacitated()
        {
            return
                new Decorator(ret =>
                    ZetaDia.Me.IsFeared ||
                    ZetaDia.Me.IsStunned ||
                    ZetaDia.Me.IsFrozen ||
                    ZetaDia.Me.IsBlind ||
                    ZetaDia.Me.IsRooted,

                    new Action(ret => RunStatus.Success)
                );
        }

        /// <summary>
        /// Creates a behavior that makes sure the bot waits for the previous spell to finish casting.
        /// </summary>
        /// <returns></returns>
        /// <remarks>Created 2012-07-11</remarks>
        public static Composite CreateWaitForAttack()
        {
            return
                new Decorator(ret => ZetaDia.Me.CommonData.AnimationState == AnimationState.Attacking,
                    new Action(ret => RunStatus.Success)
                );

        }

        /// <summary>
        /// Creates a behavior that makes sure the bot waits for the previous spell to finish casting.
        /// </summary>
        /// <returns></returns>
        /// <remarks>Created 2012-07-11</remarks>
        public static Composite CreateWaitForCast()
        {
            return
                new Decorator(ret => ZetaDia.Me.CommonData.AnimationState == AnimationState.Casting,
                    new Action(ret => RunStatus.Success)
                );

        }

        /// <summary>
        /// Gets the best potion.
        /// </summary>
        /// <remarks>Created 2012-07-11</remarks>
        private static ACDItem BestPotion
        {
            get
            {
                return
                    ZetaDia.Me.Inventory.Backpack.Where(i => i.IsPotion && i.RequiredLevel <= ZetaDia.Me.Level).
                        OrderByDescending(p => p.HitpointsGranted).FirstOrDefault();
            }
        }

        private static WaitTimer _potionCooldownTimer = WaitTimer.ThirtySeconds;
        /// <summary>
        /// Creates a behavior for using potions.
        /// </summary>
        /// <returns></returns>
        /// <remarks>Created 2012-07-11</remarks>
        public static Composite CreateUsePotion()
        {
            return
                new Decorator(ret => _potionCooldownTimer.IsFinished && ZetaDia.Me.HitpointsCurrentPct <= IncubusCCSettings.Instance.HealthPotionPct,
                    
                    new PrioritySelector(ctx => BestPotion,
                        new Decorator(ctx => ctx != null,
                            new Sequence(
                                new Action(ctx => ZetaDia.Me.Inventory.UseItem(((ACDItem)ctx).DynamicId)),
                                new Action(ctx => _potionCooldownTimer.Reset()),
                                new Action(ctx => Logger.WriteLog("Potion set to use below {0}%, my health is currently {1}%, using {2}", 100 * IncubusCCSettings.Instance.HealthPotionPct, Math.Round(100 * ZetaDia.Me.HitpointsCurrentPct), ((ACDItem)ctx).Name))
                                )
                            )
                        )
                    );
        }

        private static DiaObject HealthGlobes
        {
            get
            {
                return ZetaDia.Actors.GetActorsOfType<DiaItem>().Where(i => i.ActorSNO == 4267 && i.Distance <= IncubusCCSettings.Instance.HealthGlobeDistance).OrderBy(i => i.Distance).FirstOrDefault();
            }
        }

        private static WaitTimer _GlobeTimer = WaitTimer.OneSecond;

        public static Composite CreateGetHealthGlobe()
        {
            return
                new Decorator(ret => _GlobeTimer.IsFinished && IncubusCCSettings.Instance.GetHealthGlobe && ZetaDia.Me.HitpointsCurrentPct <= IncubusCCSettings.Instance.HealthGlobeHP,
                    new PrioritySelector(ctx => HealthGlobes,
                        new Decorator(ctx => ctx != null,
                            new Sequence(
                                Movement.MoveTo(ctx => ((DiaObject)ctx).Position, 2.5f),
                                new Action(ctx => Logger.WriteLog("Moving to Health Globe, set to use below {0}%", 100 * IncubusCCSettings.Instance.HealthGlobeHP)),
                                new Action(ctx => _GlobeTimer.Reset()),
                                new Action(ctx => Logger.WriteVerbose("Health Globe, Found one at {0}, Distance = {1}", ((DiaItem)ctx).Position, ((DiaItem)ctx).Distance)
                                )))));
        }
    }
}
